﻿define(function (require, exports, module) {
    var Canvas = require('canvas');
    var Area = require('area');
    var City = require('city');
    var Duplicate = require('duplicate');
    var Player = require('player');
    var Request = require('request');
    var Config = require('config');
    var Common = require('common');
    var m_mapCanvas = Canvas.Get(4);
    var m_drag = false;
    var m_startPos = [];
    var m_maps = [];
    var m_top = 0;
    var m_left = 0;

    function Map(data) {
        this.Data = data;
        var areas = [];
        $.each(data.Areas, function () {
            areas.push($.map(this, function (a) {
                return new Area(a);
            }));
        });
        this.Areas = areas;
        this.Cities = $.map(data.Cities, function (c) {
            return new City(c, exports);
        });
        this.Duplicates = $.map(data.Duplicates, function (d) {
            return new Duplicate(d);
        });
    };

    Map.prototype.GetLeft = function () {
        return this.Data.X - m_left;
    };

    Map.prototype.GetRight = function () {
        return this.GetLeft() + Config.GetMapWidth();
    };

    Map.prototype.GetTop = function () {
        return this.Data.Y - m_top;
    };

    Map.prototype.GetBottom = function () {
        return this.GetTop() + Config.GetMapHeight();
    };

    Map.prototype.Render = function () {
        if (Common.IsInRect({ X: this.GetLeft(), Y: this.GetTop() }, Config.GetWindowPosition()) ||
            Common.IsInRect({ X: this.GetRight(), Y: this.GetTop() }, Config.GetWindowPosition()) ||
            Common.IsInRect({ X: this.GetRight(), Y: this.GetBottom() }, Config.GetWindowPosition()) ||
            Common.IsInRect({ X: this.GetLeft(), Y: this.GetBottom() }, Config.GetWindowPosition())) {
            $.each(this.Areas, function () {
                $.each(this, function () {
                    this.Render(m_left, m_top);
                });
            });
            $.each(this.Cities, function () {
                this.Render(m_left, m_top);
            });
            $.each(this.Duplicates, function () {
                this.Render(m_left, m_top);
            });
        };
    }

    Map.prototype.IsOver = function (x, y) {
        return this.GetLeft() <= x && x < this.GetRight() && this.GetTop() <= y && y < this.GetBottom();
    };

    Map.prototype.Click = function (x, y) {
        $.each(this.Cities, function () {
            this.IsOver(x, y) && this.Enter();
        });
    };

    exports.Init = function (data) {
        var halfWidth = (Config.GetWidth() - data.MainCityWidth) / 2;
        if (data.MainCityX < halfWidth)
            m_left = 0
        else if (halfWidth < (Config.GetMaxWidth() - data.MainCityX))
            m_left = Config.GetMaxWidth() - halfWidth;
        else
            m_left = data.MainCityX + data.MainCityWidth / 2;

        var halfHeight = (Config.GetHeight() - data.MainCityHeight) / 2;
        if (data.MainCityY < halfHeight)
            m_top = 0;
        else if (halfHeight < (Config.GetMaxHeight() - data.MaxCityY))
            m_top = Config.GetMaxHeight() - halfHeight;
        else
            m_top = data.MaxCityY + data.MainCityHeight / 2;

        m_maps = $.map(data.Maps, function (m) {
            return new Map(m);
        });
    };

    exports.Show = function () {
        m_mapCanvas.Bind(module.id, {
            mousedown: function (e) {
                m_drag = true;
                m_startPos = [e.clientX, e.clientY];
            },
            mouseup: function (e) {
                m_drag = false;
                m_startPos = [];
            },
            mousemove: function (e) {
                if (m_drag) {
                    m_left += (m_startPos[0] - e.clientX);
                    if (m_left < 0) m_left = 0;
                    else if (Config.GetMoveWidth() < m_left) m_left = Config.GetMoveWidth();

                    m_top += (m_startPos[1] - e.clientY);
                    if (m_top < 0) m_top = 0;
                    else if (Config.GetMoveHeight() < m_top) m_top = Config.GetMoveHeight();

                    Render();
                    m_startPos = [e.clientX, e.clientY];
                }
            },
            mouseout: function (e) {
                m_drag = false;
                m_startPos = [];
            },
            click: function (e) {
                $.each(m_maps, function () {
                    if (this.IsOver(e.clientX, e.clientY)) {
                        this.Click(e.clientX, e.clientY);
                        return false;
                    }
                });
            }
        });

        Render();
    };

    exports.Hide = function () {
        m_mapCanvas.Unbind(module.id);
        m_mapCanvas.Clear();
    };

    function Render() {
        m_mapCanvas.Clear();
        $.each(m_maps, function () {
            this.Render();
        });
    };
});